<h1>一些简单的总结</h1>

<div>
索引：
<ul class="index summaries" id="summaries.html">
<li><a class="index" href="#type-with-underlyings">哪些种类型的值可以有间接底层部分？</a></li>
<li><a class="index" href="#have-length-types">哪些种类型的值可以用做内置<code>len</code>（以及<code>cap</code>、<code>close</code>、<code>delete</code>和<code>make</code>）函数调用的实参？</a></li>
<li><a class="index" href="#container-types">各种容器类型比较</a></li>
<li><a class="index" href="#composite-literals-types">哪些种类型的值可以用组合字面值（<code>T{...}</code>）表示？</a></li>
<li><a class="index" href="#type-sizes">各种类型的尺寸</a></li>
<li><a class="index" href="#nil-zero-value-types">哪些种类型的零值使用预声明的<code>nil</code>标识符表示？</a></li>
<li><a class="index" href="#types-can-have-methods">我们可以为什么样的类型声明方法？</a></li>
<li><a class="index" href="#types-can-be-embedded">什么样的类型可以被内嵌在结构体类型中？</a></li>
<li><a class="index" href="#compile-time-evaluation">哪些函数调用将在编译时刻被估值？</a></li>
<li><a class="index" href="#not-addressable">哪些值是可寻址的？</a></li>
<li><a class="index" href="#not-comparable">哪些类型不支持比较？</a></li>
<li><a class="index" href="#declared-but-unused">哪些代码元素允许被声明却不使用？</a></li>
<li><a class="index" href="#groupable-elements">哪些有名代码元素可多个被一起声明在一对小括号<code>()</code>中？</a></li>
<li><a class="index" href="#declaration-places">哪些有名代码元素的声明可以被声明在函数内也可以被声明在函数外？</a></li>
<li><a class="index" href="#additional-return">哪些表达式的估值结果可以包含一个额外的可选的值？</a></li>
<li><a class="index" href="#block-forever">几种导致当前协程永久阻塞的方法</a></li>
<li><a class="index" href="#concatenate-strings">几种衔接字符串的方法</a></li>
</ul>

<p>
</p>

</div>

<div class="summaries-items">

<a class="anchor" id="type-with-underlyings"></a>
<h3>
	哪些种类型的值可以有间接底层部分？
</h3>

<div>
在Go中，下列种类的类型的值可以有间接底层部分：
<ul>
<li>字符串类型</li>
<li>函数类型</li>
<li>切片类型</li>
<li>映射类型</li>
<li>通道类型</li>
<li>接口类型</li>
</ul>

<p>
注意：此答案基于标准编译器的实现。事实上，函数类型的值是否有间接底层部分是难以证明的。
另外，字符串和接口类型的值在逻辑上应该被认为是不含间接底层部分。
请阅读<a href="value-part.html">值部一文</a>获取更多信息。
</p>
</div>

<a class="anchor" id="have-length-types"></a>
<h3>
	哪些种类型的值可以用做内置<code>len</code>（以及<code>cap</code>、<code>close</code>、<code>delete</code>和<code>make</code>）函数调用的实参？
</h3>

<table border="1" class="table table-bordered text-center" style="width: auto !important;">
<thead>
	<tr>
	<th class="text-center" valign="bottom" align="center"></th>
	<th class="text-center" valign="bottom" align="center">len</th>
	<th class="text-center" valign="bottom" align="center">cap</th>
	<th class="text-center" valign="bottom" align="center">close</th>
	<th class="text-center" valign="bottom" align="center">delete</th>
	<th class="text-center" valign="bottom" align="center">make</th>
	</tr>
</thead>
<tbody>
	<tr class="active">
	<th scope="row" class="text-center" valign="middle" align="center">字符串值</th>
	<td valign="middle" align="center">可以</td>
	<td></td>
	<td></td>
	<td></td>
	<td></td>
	</tr>
	<tr>
	<th scope="row" class="text-center" valign="middle" align="center">数组或者数组指针值</th>
	<td valign="middle" align="center">可以</td>
	<td valign="middle" align="center">可以</td>
	<td></td>
	<td></td>
	<td></td>
	</tr>
	<tr class="active">
	<th scope="row" class="text-center" valign="middle" align="center">切片值</th>
	<td valign="middle" align="center">可以</td>
	<td valign="middle" align="center">可以</td>
	<td></td>
	<td></td>
	<td valign="middle" align="center">可以</td>
	</tr>
	<tr>
	<th scope="row" class="text-center" valign="middle" align="center">映射值</th>
	<td valign="middle" align="center">可以</td>
	<td></td>
	<td></td>
	<td valign="middle" align="center">可以</td>
	<td valign="middle" align="center">可以</td>
	</tr>
	<tr class="active">
	<th scope="row" class="text-center" valign="middle" align="center">通道值</th>
	<td valign="middle" align="center">可以</td>
	<td valign="middle" align="center">可以</td>
	<td valign="middle" align="center">可以</td>
	<td></td>
	<td valign="middle" align="center">可以</td>
	</tr>
</tbody>
</table>

<p>
可以被用做内置函数<code>len</code>调用的参数的值的类型都可以被称为（广义上的）容器类型。
这些容器类型的值都可以跟在<code>for-range</code>循环的<code>range</code>关键字后。
</p>

<a class="anchor" id="container-types"></a>
<h3>
	各种容器类型比较
</h3>

<table border="1" class="table table-bordered text-center" style="width: auto !important;">
<thead>
	<tr>
	<th class="text-center" valign="bottom" align="center">类型</th>
	<th class="text-center" valign="bottom" align="center">容器值是否支持添加新的元素？</th>
	<th class="text-center" valign="bottom" align="center">容器值中的元素是否可以被替换？</th>
	<th class="text-center" valign="bottom" align="center">容器值中的元素是否可寻址？</th>
	<th class="text-center" valign="bottom" align="center">访问容器值元素是否会更改容器长度？</th>
	<th class="text-center" valign="bottom" align="center">容器值是否可以有间接底层部分？</th>
	</tr>
</thead>
<tbody>
	<tr class="active">
	<th scope="row" class="text-center" style="white-space: nowrap;" valign="middle" align="center">字符串</th>
	<td valign="middle" align="center">否</td>
	<td valign="middle" align="center">否</td>
	<td valign="middle" align="center">否</td>
	<td valign="middle" align="center">否</td>
	<td valign="middle" align="center">是<sup>(1)</sup></td>
	</tr>
	<tr>
	<th scope="row" class="text-center" style="white-space: nowrap;" valign="middle" align="center">数组</th>
	<td valign="middle" align="center">否</td>
	<td valign="middle" align="center">是<sup>(2)</sup></td>
	<td valign="middle" align="center">是<sup>(2)</sup></td>
	<td valign="middle" align="center">否</td>
	<td valign="middle" align="center">否</td>
	</tr>
	<tr class="active">
	<th scope="row" class="text-center" style="white-space: nowrap;" valign="middle" align="center">切片</th>
	<td valign="middle" align="center">否<sup>(3)</sup></td>
	<td valign="middle" align="center">是</td>
	<td valign="middle" align="center">是</td>
	<td valign="middle" align="center">否</td>
	<td valign="middle" align="center">是</td>
	</tr>
	<tr>
	<th scope="row" class="text-center" style="white-space: nowrap;" valign="middle" align="center">映射</th>
	<td valign="middle" align="center">是</td>
	<td valign="middle" align="center">是</td>
	<td valign="middle" align="center">否</td>
	<td valign="middle" align="center">否</td>
	<td valign="middle" align="center">是</td>
	</tr>
	<tr class="active">
	<th scope="row" class="text-center" style="white-space: nowrap;" valign="middle" align="center">通道</th>
	<td valign="middle" align="center">是<sup>(4)</sup></td>
	<td valign="middle" align="center">否</td>
	<td valign="middle" align="center">否</td>
	<td valign="middle" align="center">是</td>
	<td valign="middle" align="center">是</td>
	</tr>
</tbody>
</table>

<p>
<sup>(1)</sup> 对于标准编译器和运行时来说。
<br/>
<sup>(2)</sup> 对于可寻址的数组值来说。
<br/>
<sup>(3)</sup> 一般说来，一个切片的长度只能通过将另外一个切片赋值给它来被整体替换修改，这里我们不视这种情况为“添加新的元素”。
其实，切片的长度也可以通过调用<code>reflect.SetLen</code>来单独修改。增加切片的长度可以看作是一种变相的向切片添加元素。
但<code>reflect.SetLen</code>函数的效率很低，因此很少使用。
<br/>
<sup>(4)</sup> 对于带缓冲并且缓冲未满的通道来说。
</p>

<a class="anchor" id="composite-literals-types"></a>
<h3>
	哪些种类型的值可以用组合字面值（<code>T{...}</code>）表示？
</h3>

<p>
下面在四种类型的值（除了切片和映射类型的零值）可以用组合字面值表示。
</p>

<table border="1" class="table table-bordered text-center" style="width: auto !important;">
<thead>
	<tr>
	<th class="text-center" valign="bottom" align="center">类型（<code>T</code>）</th>
	<th class="text-center" valign="bottom" align="center"><code>T{}</code>是类型<code>T</code>的零值？</th>
	</tr>
</thead>
<tbody>
	<tr class="active">
	<th scope="row" class="text-center" valign="middle" align="center">结构体类型</th>
	<td valign="middle" align="center">是</td>
	</tr>
	<tr>
	<th scope="row" class="text-center" valign="middle" align="center">数组类型</th>
	<td valign="middle" align="center">是</td>
	</tr>
	<tr class="active">
	<th scope="row" class="text-center" style="vertical-align: middle" valign="middle" align="center">切片类型</th>
	<td valign="middle" align="center">否<br/>（零值用<code>nil</code>表示）</td>
	</tr>
	<tr>
	<th scope="row" class="text-center" style="vertical-align: middle" valign="middle" align="center">映射类型</th>
	<td valign="middle" align="center">否<br/>（零值用<code>nil</code>表示）</td>
	</tr>
</tbody>
</table>

<a class="anchor" id="type-sizes"></a>
<h3>
	各种类型的尺寸
</h3>

<p>
详见<a href="value-copy-cost.html">值复制成本</a>一文。
</p>

<a class="anchor" id="nil-zero-value-types"></a>
<h3>
	哪些种类型的零值使用预声明的<code>nil</code>标识符表示？
</h3>

<p>
下面这些类型的零值可以用预声明的<code>nil</code>标识符表示。
</p>

<table border="1" class="table table-bordered text-center" style="width: auto !important;">
<thead>
	<tr>
	<th class="text-center" valign="bottom" align="center">类型（<code>T</code>）</th>
	<th class="text-center" valign="bottom" align="center"><code>T(nil)</code>的尺寸</th>
	</tr>
</thead>
<tbody>
	<tr class="active">
	<th scope="row" class="text-center">指针</th>
	<td>1 word</td>
	</tr>
	<tr>
	<th scope="row" class="text-center">切片</th>
	<td>3 words</td>
	</tr>
	<tr class="active">
	<th scope="row" class="text-center">映射</th>
	<td>1 word</td>
	</tr>
	<tr>
	<th scope="row" class="text-center">通道</th>
	<td>1 word</td>
	</tr>
	<tr class="active">
	<th scope="row" class="text-center">函数</th>
	<td>1 word</td>
	</tr>
	<tr>
	<th scope="row" class="text-center">接口</th>
	<td>2 words</td>
	</tr>
</tbody>
</table>

<p>
上表列出的尺寸为标准编译器的结果。
一个word（原生字）在32位的架构中为4个字节，在64位的架构中为8个字节。
一个Go值的<a href="value-part.html">间接底层部分</a>未统计在尺寸中。
</p>

<p>
一个类型的零值的尺寸和其它非零值的尺寸是一致的。
</p>

<a class="anchor" id="types-can-have-methods"></a>
<h3>
	我们可以为什么样的类型声明方法？
</h3>

<p>
详见<a href="method.html">方法</a>一文。
</p>

<a class="anchor" id="types-can-be-embedded"></a>
<h3>
	什么样的类型可以被内嵌在结构体类型中？
</h3>

<p>
详见<a href="type-embedding.html#embeddable-types">类型内嵌</a>一文。
</p>

<a class="anchor" id="compile-time-evaluation"></a>
<h3>
	哪些函数调用将在编译时刻被估值？
</h3>

<p>
如果一个函数调用在编译时刻被估值，则估值结果为一个常量。
</p>

<table border="1" class="table table-bordered text-center" style="width: auto !important;">
<thead>
	<tr>
	<th class="text-center" valign="bottom" align="center">函数</th>
	<th class="text-center" valign="bottom" align="center">返回类型</th>
	<th class="text-center" valign="bottom" align="center">其调用是否总是在编译时刻估值？</th>
	</tr>
</thead>
<tbody>
	<tr class="active">
	<th scope="row" class="text-center">unsafe.Sizeof</th>
	<td rowspan="3" style="vertical-align: middle"><code>uintptr</code></td>
	<td rowspan="3" style="vertical-align: middle">是</td>
	</tr>
	<tr class="active">
	<th scope="row" class="text-center" style="vertical-align: middle">unsafe.Alignof</th>
	</tr>
	<tr class="active">
	<th scope="row" class="text-center" style="vertical-align: middle">unsafe.Offsetof</th>
	</tr>
	<tr>
	<th scope="row" class="text-center" style="vertical-align: middle" valign="middle" align="center"><br/><br/>len<br/><br/><br/></th>
	<td rowspan="2" style="vertical-align: middle" valign="middle" align="center"><code>int</code></td>
	<td rowspan="2" valign="middle" align="center">
		否
		<br/><br/>
		<div class="text-left">
		<a href="https://golang.google.cn/ref/spec#Length_and_capacity">Go语言白皮书</a>中提到：
		<ul>
		<li>
		如果表达式<code>s</code>表示一个字符串常量，则表达式<code>len(s)</code>将在编译时刻估值；
		</li>
		<li>
		如果表达式<code>s</code>表示一个数组或者数组的指针，并且<code>s</code>中不含有数据接收操作和估值结果为非常量的函数调用，则表达式<code>len(s)</code>和<code>cap(s)</code>将在编译时刻估值。
		</li>
		</ul>
		</div>
	</td>
	</tr>
	<tr>
	<th scope="row" class="text-center" style="vertical-align: middle" valign="middle" align="center"><br/><br/>cap<br/><br/><br/></th>
	</tr>
	<tr class="active">
	<th scope="row" class="text-center" style="vertical-align: middle" valign="middle" align="center"><br/>real<br/><br/></th>
	<td rowspan="2" style="vertical-align: middle" valign="middle" align="center">
		默认类型为<br/><code>float64</code><br/>（结果为类型不确定值）
	</td>
	<td rowspan="2" valign="middle" align="center">
		否
		<br/><br/>
		<div class="text-left">
		<a href="https://golang.google.cn/ref/spec#Constants">Go语言白皮书</a>提到：
		表达式<code>real(s)</code>和<code>imag(s)</code>在<code>s</code>为一个复数常量表达式时才在编译时刻估值。
		</div>
	</td>
	</tr>
	<tr class="active">
	<th scope="row" class="text-center" style="vertical-align: middle" valign="middle" align="center"><br/>imag<br/><br/></th>
	</tr>
	<tr>
	<th scope="row" class="text-center" style="vertical-align: middle" valign="middle" align="center">complex</th>
	<td style="vertical-align: middle" valign="middle" align="center">
		默认类型为<br/><code>complex128</code><br/>（结果为类型不确定值）
	</td>
	<td valign="middle" align="center">
		否
		<br/><br/>
		<div class="text-left">
		<a href="https://golang.google.cn/ref/spec#Constants">Go语言白皮书</a>提到：
		表达式<code>complex(sr, si)</code>只有在<code>sr</code>和<code>si</code>都为常量表达式的时候才在编译时刻估值。
		</div>
	</td>
	</tr>
</tbody>
</table>

<a class="anchor" id="not-addressable"></a>
<h3>
	哪些值是可寻址的？
</h3>

<p>
请阅读<a href="unofficial-faq.html#unaddressable-values">此条问答</a>获取详情。
</p>

<a class="anchor" id="not-comparable"></a>
<h3>
	哪些类型不支持比较？
</h3>

<p>
请阅读<a href="unofficial-faq.html#uncomparable-types">此条问答</a>获取详情。
</p>

<a class="anchor" id="declared-but-unused"></a>
<h3>
	哪些代码元素允许被声明却不使用？
</h3>

<table border="1" class="table table-bordered text-center" style="width: auto !important;">
<thead>
	<tr>
	<th class="text-center" valign="bottom" align="center"></th>
	<th class="text-center" valign="bottom" align="center">允许被声明却不使用？</th>
	</tr>
</thead>
<tbody>
	<tr class="active">
	<th scope="row" class="text-center">包引入</th>
	<td>不允许</td>
	</tr>
	<tr>
	<th scope="row" class="text-center">类型</th>
	<td>允许</td>
	</tr>
	<tr class="active">
	<th scope="row" class="text-center" valign="middle" align="center">变量</th>
	<td valign="middle" align="center">
		包级全局变量允许，但局部变量不允许（对于官方标准编译器）。
	</td>
	</tr>
	<tr>
	<th scope="row" class="text-center">常量</th>
	<td>允许</td>
	</tr>
	<tr class="active">
	<th scope="row" class="text-center">函数</th>
	<td>允许</td>
	</tr>
	<tr>
	<th scope="row" class="text-center">跳转标签</th>
	<td>不允许</td>
	</tr>
</tbody>
</table>

<a class="anchor" id="groupable-elements"></a>
<h3>
	哪些有名代码元素可多个被一起声明在一对小括号<code>()</code>中？
</h3>

<div>
下面这些同种类的代码元素可多个被一起声明在一对小括号<code>()</code>中：
<ul>
<li>包引入</li>
<li>类型</li>
<li>变量</li>
<li>常量</li>
</ul>
</div>
<p>
函数是不能多个被一起声明在一对小括号<code>()</code>中的。跳转标签也不能。
</p>

<a class="anchor" id="declaration-places"></a>
<h3>
	哪些代码元素的声明可以被声明在函数内也可以被声明在函数外？
</h3>

<div>
下面这些代码元素的声明既可以被声明在函数内也可以被声明在函数外：
<ul>
<li>类型</li>
<li>变量</li>
<li>常量</li>
</ul>
</div>
<p>
包引入必须被声明在其它种类的代码元素的声明之前。
</p>
<p>
函数必须声明在任何函数体之外。匿名函数可以定义在函数体内，但那不属于声明。
</p>
<p>
跳转标签必须声明在函数体内。
</p>

<a class="anchor" id="additional-return"></a>
<h3>
	哪些表达式的估值结果可以包含一个额外的可选的值？
</h3>

<p>
下列表达式的估值结果可以包含一个额外的可选的值：
</p>

<table border="1" class="table table-bordered text-center" style="width: auto !important;">
<thead>
	<tr>
	<th class="text-center" valign="bottom" align="center"></th>
	<th class="text-center" valign="bottom" align="center">语法</th>
	<th class="text-center" valign="bottom" align="center">额外的可选的值（语法示例中的<code>ok</code>）的含义</th>
	<th class="text-center" valign="bottom" align="center">舍弃额外的可选的值会对估值行为发生影响吗？</th>
	</tr>
</thead>
<tbody>
	<tr class="active">
	<th scope="row" class="text-center" style="vertical-align: middle" valign="middle" align="center">映射元素访问</th>
	<td style="vertical-align: middle; white-space: nowrap;" class="text-center" valign="middle" align="center">
		<code>e, ok = aMap[key]</code>
	</td>
	<td valign="middle" align="center">键值<code>key</code>对应的条目是否存储在映射值中</td>
	<td valign="middle" align="center">否</td>
	</tr>
	<tr>
	<th scope="row" class="text-center" style="vertical-align: middle" valign="middle" align="center">数据接收</th>
	<td style="vertical-align: middle; white-space: nowrap;" class="text-center" valign="middle" align="center">
		<code>e, ok = &lt;- aChannel</code>
	</td>
	<td valign="middle" align="center">被接收到的值<code>e</code>是否是在通道关闭之前发送的</td>
	<td valign="middle" align="center">否</td>
	</tr>
	<tr class="active">
	<th scope="row" class="text-center" style="vertical-align: middle" valign="middle" align="center">类型断言</th>
	<td style="vertical-align: middle; white-space: nowrap;" class="text-center" valign="middle" align="center">
		<code>v, ok = anInterface.(T)</code>
	</td>
	<td valign="middle" align="center">接口值的动态类型是否为类型<code>T</code></td>
	<td valign="middle" align="center">是<br/>（当可选的值被舍弃并且断言失败的的时候，将产生一个恐慌。）</td>
	</tr>
</tbody>
</table>

<a class="anchor" id="block-forever"></a>
<h3>
	几种导致当前协程永久阻塞的方法
</h3>

<div>
无需引入任何包，我们可以使用下面几种方法使当前协程永久阻塞：
<ol>
<li>向一个永不会被接收数据的通道发送数据。
	<div>
<pre class="disable-line-numbers111"><code class="language-go">make(chan struct{}) <- struct{}{}
// 或者
make(chan<- struct{}) <- struct{}{}
</code></pre>
	</div>
</li>
<li>从一个未被并且将来也不会被发送数据的（并且保证永不会被关闭的）通道读取数据。
	<div>
<pre class="disable-line-numbers111"><code class="language-go"><-make(chan struct{})
// 或者
<-make(<-chan struct{})
// 或者
for range make(<-chan struct{}) {}
</code></pre>
	</div>
</li>
<li>从一个nil通道读取或者发送数据。
	<div>
<pre class="disable-line-numbers111"><code class="language-go">chan struct{}(nil) <- struct{}{}
// 或者
<-chan struct{}(nil)
// 或者
for range chan struct{}(nil) {}
</code></pre>
	</div>
</li>
<li>使用一个不含任何分支的<code>select</code>流程控制代码块。
	<div>
<pre class="disable-line-numbers111"><code class="language-go">select{}
</code></pre>
	</div>
</li>
</ol>
</div>

<a class="anchor" id="concatenate-strings"></a>
<h3>
	几种衔接字符串的方法
</h3>

<p>
详见<a href="string.html#string-concatenation">字符串</a>一文。
</p>




</div> <!-- summaries-items -->

<!--

Fatal errors which can be recovered:
* https://play.golang.org/p/bYrfLTzXpc_o bad Mutex.Unlock call
* create goroutine with nil function
* memory allcaotion fails

The optimizations made by gc
* len([]rune(str)) // since Go 1.11
* string ...
  []byte <-> stirng
  len([]rune(string))
  string + string
* since Go 1.11, https://github.com/golang/go/issues/21266#issuecomment-384706868
  possible future append(s, make([]T)) optimiation
  https://docs.google.com/presentation/d/1tpeJZFObkeick4CF-mx0L3CeCgvT15B96aJeRpxEPcE/preview#slide=id.g3bc6fcf60c_0_62
* memclr
* interface copy
* interface dynamic pointer value
* 4 fields struct is much faster than more field struct
  https://docs.google.com/presentation/d/1tpeJZFObkeick4CF-mx0L3CeCgvT15B96aJeRpxEPcE/preview#slide=id.g3bc6fcf60c_0_157
* BCE
  https://docs.google.com/presentation/d/1tpeJZFObkeick4CF-mx0L3CeCgvT15B96aJeRpxEPcE/preview#slide=id.g3bc6fcf60c_0_169


short and standard variable declaration comparison

differences between built-in functions and custom functions.
  * generic
  * built-in function returns can't be omitted
  * builtin-in functions can't be used as values, they have no types.
  * built-in doon't need to be imported before using them, even their identifiers starts with lower..
  *

built-in function list

	"append":  predeclaredFunction,
	"cap":     predeclaredFunction,
	"close":   predeclaredFunction,
	"complex": predeclaredFunction,
	"copy":    predeclaredFunction,
	"delete":  predeclaredFunction,
	"imag":    predeclaredFunction,
	"len":     predeclaredFunction,
	"make":    predeclaredFunction,
	"new":     predeclaredFunction,
	"panic":   predeclaredFunction,
	"print":   predeclaredFunction,
	"println": predeclaredFunction,
	"real":    predeclaredFunction,
	"recover": predeclaredFunction,


#returns-discardable
return results of calls to which built-in functions can be discarded.

values of which kinds of types can be for-ranged.

ways to return a function: naturally return, return keyword, panic, runtime.Goexit()

the form <code>v[k]</code> can be used to access element of value of which kinds of types?



-->

<!--
todo:
	kinds of control flow blocks
	control flow statements
		return, break, fallthrough, continue, goto
	which control flow statements can be followed a label.
	which control flow statements can appean in which control flow blocks

-->
